using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Data;

namespace GuavaData
{
    public class TableRef : Operator
    {
        #region Fields
        string table;
        public string Table
        {
            get { return table; }
            set { table = value; }
        }

        string alias;
        public string Alias
        {
            get { return alias; }
            set { alias = value; }
        }

        List<string> columns;
        public List<string> Columns
        {
            get { return columns; }
            set { columns = value; }
        }
        #endregion Fields

        public TableRef(string table, string alias)
        {
            this.table = table;
            this.alias = alias;
            this.columns = new List<string>();
            this.exposedColumns = new List<string>();
            this.exposedDomains = new List<GuavaData.Domain.Domain>();
            this.parent = null;
        }

        public TableRef(string table, string alias, IEnumerable<string> columns, IEnumerable<string> columnAliases, IEnumerable<Domain.Domain> domains)
        {
            this.table = table;
            this.alias = alias;
            this.columns = new List<string>(columns);
            this.exposedColumns = new List<string>(columnAliases);
            this.exposedDomains = new List<GuavaData.Domain.Domain>(domains);
            this.parent = null;

            if (exposedDomains.Count != exposedColumns.Count)
            {
                throw new Exception("Number of column aliases does not match the number of column domains in table " + alias + ".");
            }
            if (this.columns.Count != exposedColumns.Count)
            {
                throw new Exception("Number of column aliases does not match the number of columns in table " + alias + ".");
            }
        }

        public override SqlText Visit(Provider qv)
        {
            return qv.Transform(this);
        }
        public override void Visit(Transform t, Command c)
        {
            t.Expand(this, c);
        }

        public override void Visit(Channel c, string table)
        {
            c.MapAliases(this, table);
        }

        public override Operator Clone()
        {
            return new TableRef(this.table, this.alias, this.columns, this.exposedColumns, this.exposedDomains);
        }

        public void AddColumn(string column, string columnAlias, Domain.Domain domain)
        {
            this.columns.Add(column);
            this.exposedColumns.Add(columnAlias);
            this.exposedDomains.Add(domain);
        }

        public override void NotifyChange(Operator old, Operator newOp)
        {
            // Nothing to change
            return;
        }

        new public static TableRef FromXElement(XElement x)
        {
            string table = x.Attribute("table").Value;
            string alias = x.Attribute("alias").Value;
            List<string> columns = new List<string>();
            List<string> aliases = new List<string>();
            List<GuavaData.Domain.Domain> domains = new List<GuavaData.Domain.Domain>();

            foreach (XElement att in x.Elements()){
                columns.Add(att.Attribute("cName").Value);
                aliases.Add(att.Attribute("aName").Value);//alias + "." + att.Attribute("cName").Value);
                DataTable dt = new DataTable();
                DataColumn dc = new DataColumn("Data_Type", System.Type.GetType("System.String"));
                dt.Columns.Add(dc);
                DataRow dr = dt.NewRow();
                dr["Data_Type"] = att.Attribute("domain").Value;
                domains.Add(GuavaData.Domain.Domain.FromDBInfoRow(dr));
            }

            if (!(table == null))
                return new TableRef(table, alias, columns, aliases, domains);
            else
                throw new Exception("While loading TableRef from XML: table was null");
        }
    }
}
